package com.xiongjie.SingleLimit.algorithm;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;

/**
 * 使用时间变量完成固定窗口的限流算法
 */
public class FWLimiterWithoutMT implements Limiter {

    //作为变量锁，同步操作
    private Long lastVisitAt = System.currentTimeMillis();
    private AtomicInteger count=new AtomicInteger(0);

    @Override
    public boolean isOverLimit() {
        return currentQPS() > 5;
    }

    @Override
    public int currentQPS() {
        return count.get();
    }

    /**
     * 将限流操作和定时重置放到同一个方法中执行
     *
     * @return
     */
    @Override
    public boolean visit() {

        //这里当访问时间小于1秒时，可以继续++，但是超过阈值则丢弃
        //如果访问时间大于1秒，则重置计数器
        long now = System.currentTimeMillis();
        synchronized (lastVisitAt) {
            if (now - lastVisitAt > 1000) {
                lastVisitAt = now;
                System.out.println(currentQPS());
                count.set(0);
            }
        }

        count.incrementAndGet();
        return isOverLimit();
    }

    public static void main(String[] args) {
        Limiter rateLimiter = new FWLimiterWithoutMT();

        //模拟0.1秒中发送一次请求
        IntStream.range(0, 2).forEach(i -> {
            new Thread(() -> {
                while (true) {
                    boolean res = rateLimiter.visit();
                    System.out.print(res + "\t");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        });
    }
}
